﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

public class EByte
{
    private MemoryStream ms;

    public static EByte EByteNew()
    {
        return new EByte();
    }

    public static EByte EByteNew(byte[] data)
    {
        return new EByte(data);
    }

    public EByte()
    {
        ms = new MemoryStream();
    }

    public EByte(byte[] data)
    {
        ms = new MemoryStream(data);
        this.setPosition(0);
    }

    public EByte WriteByte(byte b)
    {
        ms.WriteByte(b);
        return this;
    }

    public EByte WriteBytes(byte[] data)
    {
        ms.Write(data, 0, data.Length);
        return this;
    }

    public EByte WriteShort(short s)
    {
        ms.WriteByte((byte)(s >> 0));
        ms.WriteByte((byte)(s >> 8));
        return this;
    }

    public EByte WriteInt(int i)
    {
        ms.WriteByte((byte)(i >> 0));
        ms.WriteByte((byte)(i >> 8));
        ms.WriteByte((byte)(i >> 16));
        ms.WriteByte((byte)(i >> 24));
        return this;
    }

    public EByte WriteLong(long i)
    {
        ms.WriteByte((byte)(i >> 0));
        ms.WriteByte((byte)(i >> 8));
        ms.WriteByte((byte)(i >> 16));
        ms.WriteByte((byte)(i >> 24));
        ms.WriteByte((byte)(i >> 32));
        ms.WriteByte((byte)(i >> 40));
        ms.WriteByte((byte)(i >> 48));
        ms.WriteByte((byte)(i >> 56));
        return this;
    }

    public EByte WriteFloat(float f)
    {
        byte[] data = BitConverter.GetBytes(f);
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(data);
        }
        ms.Write(data, 0, data.Length);
        return this;
    }

    public EByte WriteByteArray(List<Byte> bytes)
    {
        if (bytes == null)
        {
            bytes = new List<byte>();
        }
        this.WriteInt(bytes.Count);
        for (int i = 0; i < bytes.Count; i++)
        {
            this.WriteByte(bytes[i]);
        }
        return this;
    }

    public EByte WriteByteArray(byte[] bytes)
    {
        if (bytes == null)
        {
            bytes = new byte[0];
        }
        this.WriteInt(bytes.Length);
        for (int i = 0; i < bytes.Length; i++)
        {
            this.WriteByte(bytes[i]);
        }
        return this;
    }

    public EByte WriteIntArray(List<int> ints)
    {
        if (ints == null)
        {
            ints = new List<int>();
        }
        this.WriteInt(ints.Count);
        for (int i = 0; i < ints.Count; i++)
        {
            this.WriteInt(ints[i]);
        }
        return this;
    }


    public EByte WriteIntArray(int[] ints)
    {
        if (ints == null)
        {
            ints = new int[0];
        }
        this.WriteInt(ints.Length);
        for (int i = 0; i < ints.Length; i++)
        {
            this.WriteInt(ints[i]);
        }
        return this;
    }

    public EByte WriteString(string s)
    {
        if (s == null) s = "";
        byte[] data = Encoding.UTF8.GetBytes(s);
        this.WriteShort((short)data.Length);
        this.WriteBytes(data);
        return this;
    }

    public void setPosition(int position)
    {
        ms.Position = position;
    }

    public int getPosition()
    {
        return (int)ms.Position;
    }

    public bool isEnd()
    {
        return (bool)(ms.Position >= ms.Length);
    }

    public byte ReadByte()
    {
        return (byte)ms.ReadByte();
    }

    public short ReadShort()
    {
        return (short)(((ms.ReadByte() & 0xff) | (ms.ReadByte() << 8)));
    }

    public int ReadInt()
    {
        return (int)((((ms.ReadByte() & 0xff) << 0)
                      | ((ms.ReadByte() & 0xff) << 8)
                      | ((ms.ReadByte() & 0xff) << 16)
                      | ((ms.ReadByte() & 0xff) << 24)));
    }

    public long ReadLong()
    {
        return ((long)(ms.ReadByte() & 0xff) << 0)
              | ((long)(ms.ReadByte() & 0xff) << 8)
              | ((long)(ms.ReadByte() & 0xff) << 16)
              | ((long)(ms.ReadByte() & 0xff) << 24)
              | ((long)(ms.ReadByte() & 0xff) << 32)
              | ((long)(ms.ReadByte() & 0xff) << 40)
              | ((long)(ms.ReadByte() & 0xff) << 48)
              | ((long)(ms.ReadByte() & 0xff) << 56);
    }

    public float ReadFloat()
    {
        byte[] data = { (byte)ms.ReadByte(), (byte)ms.ReadByte(), (byte)ms.ReadByte(), (byte)ms.ReadByte() };
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(data);
        }
        return BitConverter.ToSingle(data, 0);
    }

    public string ReadString()
    {
        byte[] data = new byte[this.ReadShort()];
        ms.Read(data, 0, data.Length);
        return Encoding.UTF8.GetString(data);
    }

    public byte[] ReadByteArray()
    {
        int n = this.ReadInt();
        byte[] data = new byte[n];
        ms.Read(data, 0, data.Length);
        return data;
    }

    public int[] ReadIntArray()
    {
        int n = ReadInt();
        int[] data = new int[n];
        for (int i = 0; i < n; ++i)
        {
            data[i] = ReadInt();
        }
        return data;
    }

    public byte[] Bytes()
    {
        return ms.GetBuffer();
    }

    public byte[] Package()
    {
        byte[] data = ms.ToArray();
        return ms.ToArray();
    }

    public override string ToString()
    {
        int now_pos = (int)ms.Position;
        this.ms.Position = 0;
        string str = "";
        for (int i = 0; i < this.ms.Length; i++)
        {
            str += this.ReadByte().ToString();
            if (i + 1 < this.ms.Length)
            {
                str += ",";
            }
        }
        this.ms.Position = now_pos;
        return str;
    }

    public void Free()
    {
        this.ms.Close();
    }
}